home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-03 | 26.3 KB | 815 lines | [TEXT/MPS ] |
- //----------------------------------------------------------------------------------------
- // UDependencies.cp
- // Copyright © 1988-96 by Apple Computer, Inc. All rights reserved.
- //----------------------------------------------------------------------------------------
-
- #ifndef __UDEPENDENCIES__
- #include "UDependencies.h"
- #endif
-
- // MacApp
-
- #ifndef __UITERATOR__
- #include "UIterator.h"
- #endif
-
- // Toolbox
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
-
- //========================================================================================
- // struct CDependencyComparer
- //========================================================================================
-
- struct CDependencyComparer
- {
- public:
- Dependency& fTargetDependency;
- TDependencies* fDependencies;
-
- // Constructor
- inline CDependencyComparer(Dependency& targetDependency,
- TDependencies* theDependencies) :
- fTargetDependency(targetDependency),
- fDependencies(theDependencies)
- { }
- };
-
-
- //========================================================================================
- // GLOBAL Variables
- //========================================================================================
-
- TDependencySpace* gMacAppDependencies;
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- static TDependencies* NewDependencies();
- static CompareResult CompareDependency(ArrayIndex index,
- void* yourDataPtr);
-
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // NewDependencies:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TDependencies* NewDependencies()
- {
- TDependencies * dependencies = new TDependencies;
- dependencies->IDependencies();
-
- return dependencies;
- }
-
-
- //========================================================================================
- // CLASS TNotificationQueue
- //========================================================================================
- #undef Inherited
- #define Inherited TDynamicArray
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TNotificationQueue,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TNotificationQueue::NewNotificationQueue:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TNotificationQueue* TNotificationQueue::NewNotificationQueue()
- {
- MAVolatileInit(TNotificationQueue * , it, new TNotificationQueue);
- FailInfo fi;
- Try(fi)
- {
- it->INotificationQueue();
- fi.Success();
- }
- else // Recover
- {
- it->Free();
- fi.ReSignal();
- }
-
- return it;
- }
-
- //----------------------------------------------------------------------------------------
- // TNotificationQueue destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TNotificationQueue::~TNotificationQueue()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TNotificationQueue::Dequeue:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- Boolean TNotificationQueue::Dequeue(Notification& item)
- {
- Boolean available = (fSize > 0);
- if (available)
- {
- GetElementsAt(1, &item, 1);
- DeleteElementsAt(1, 1);
- }
-
- return available;
- }
-
- //========================================================================================
- // CLASS TDependencies
- //========================================================================================
- #undef Inherited
- #define Inherited TSortedDynamicArray
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TDependencies,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TDependencies destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TDependencies::~TDependencies()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencies::AddDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencies::AddDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel)
- {
- ArrayIndex index;
-
- if (!FindDependency(notifier, dependent, dependencyLabel, index))
- InsertDependencyBefore(index, notifier, dependent, dependencyLabel);
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencies::InsertDependencyBefore:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencies::InsertDependencyBefore(ArrayIndex index,
- TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel)
- {
- Dependency newDependency(notifier, dependent, dependencyLabel);
-
- InsertElementsBefore(index, &newDependency, 1);
- }
-
-
- //----------------------------------------------------------------------------------------
- // TDependencies::FindDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- Boolean TDependencies::FindDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel,
- ArrayIndex& index)
-
-
- {
- Dependency targetDependency(notifier, dependent, dependencyLabel);
- CDependencyComparer aDependencyComparer(targetDependency, this);
-
- return DoSearchElement(&CompareDependency, &aDependencyComparer, index);
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencies::FindPrimaryObject:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- Boolean TDependencies::FindPrimaryObject(TObject* notifier,
- ArrayIndex& index)
- {
- Dependency targetDependency(notifier, NULL, kNoLabel);
- CDependencyComparer aDependencyComparer(targetDependency, this);
-
- return DoSearchElement(&CompareDependency, &aDependencyComparer, index);
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencies::RemoveDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencies::RemoveDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel)
- {
- ArrayIndex index;
-
- if (FindDependency(notifier, dependent, dependencyLabel, index))
- DeleteElementsAt(index, 1);
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencies::CompareElements:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CompareResult TDependencies::CompareElements(void* Element1,
- void* Element2)// Override
-
- {
- CompareResult returnVal;
-
- Dependency & Dependency1 = *((DependencyPtr)Element1);
- Dependency & Dependency2 = *((DependencyPtr)Element2);
-
- if (Dependency1.fPrimaryObject > Dependency2.fPrimaryObject)
- returnVal = kItem1GreaterThanItem2;
- else if (Dependency1.fPrimaryObject < Dependency2.fPrimaryObject)
- returnVal = kItem1LessThanItem2;
- else
- {
- if ((Dependency1.fSecondaryObject == NULL) || (Dependency2.fSecondaryObject == NULL) || (Dependency1.fSecondaryObject == Dependency2.fSecondaryObject))
- returnVal = kItem1EqualItem2;
- else if (Dependency1.fSecondaryObject < Dependency2.fSecondaryObject)
- returnVal = kItem1LessThanItem2;
- else
- returnVal = kItem1GreaterThanItem2;
- }
-
- return returnVal;
- }
-
-
- //========================================================================================
- // CLASS TDependencySpace
- //========================================================================================
- #undef Inherited
- #define Inherited TObject
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TDependencySpace,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TDependencySpace::~TDependencySpace()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace::AddDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencySpace::AddDependency(TObject* /*notifier*/ ,
- TObject* /*dependent*/ ,
- DependencyLabels/*dependencyLabel*/ )
- {
- SubClassResponsibility();
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace::RemoveDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencySpace::RemoveDependency(TObject*/*notifier*/ ,
- TObject*/*dependent*/ ,
- DependencyLabels/*dependencyLabel*/ )
- {
- SubClassResponsibility();
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace::NotifierChanged:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencySpace::NotifierChanged(TObject* /*notifier*/ ,
- ChangeID /*theChange*/,
- TObject* /*changedBy*/ )// Override
- {
- SubClassResponsibility();
- }
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace::RemoveDependencies:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TDependencySpace::RemoveDependencies(TObject*/*anObject*/ )
- {
- SubClassResponsibility();
- }
-
-
- //========================================================================================
- // CLASS TSimpleDependencySpace
- //========================================================================================
- #undef Inherited
- #define Inherited TDependencySpace
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TSimpleDependencySpace,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace constructor
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TSimpleDependencySpace::TSimpleDependencySpace() :
- fDependents(NULL),
- fNotifiers(NULL)
- {
- }
- // TSimpleDependencySpace::TSimpleDependencySpace
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace::Free:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TSimpleDependencySpace::~TSimpleDependencySpace()
-
- {
- fDependents = (TDependencies *)FreeIfObject(fDependents);
- fNotifiers = (TDependencies *)FreeIfObject(fNotifiers);
- }
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace::AddDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TSimpleDependencySpace::AddDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel)// Override
- {
- if (fDependents == NULL)
- fDependents = NewDependencies();
- if (fNotifiers == NULL)
- fNotifiers = NewDependencies();
- fDependents->AddDependency(notifier, dependent, dependencyLabel);
- fNotifiers->AddDependency(dependent, notifier, dependencyLabel);
- }
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace::RemoveDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TSimpleDependencySpace::RemoveDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel)// Override
- {
- if (fDependents)
- fDependents->RemoveDependency(notifier, dependent, dependencyLabel);
- if (fNotifiers)
- fNotifiers->RemoveDependency(dependent, notifier, dependencyLabel);
- }
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace::NotifierChanged:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TSimpleDependencySpace::NotifierChanged(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy)// Override
- {
- CDependentIterator iter(notifier, this);
-
- for (TObject * dependent = iter.FirstDependent(); iter.More(); dependent = iter.NextDependent())
- dependent->DoUpdate(theChange, notifier, changedBy, this);
- }
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace::RemoveDependencies:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TSimpleDependencySpace::RemoveDependencies(TObject* anObject)// Override
- {
- {
- CDependentIterator iter(anObject, this);
-
- for (TObject * dependent = iter.FirstDependent(); iter.More(); dependent = iter.NextDependent())
- {
- fDependents->DeleteElementsAt(iter.fCurrentIndex, 1);
- fNotifiers->RemoveDependency(dependent, anObject, kNoLabel);
- }
- }
- {
- CNotifierIterator iter(anObject, this);
-
- for (TObject * notifier = iter.FirstNotifier(); iter.More(); notifier = iter.NextNotifier())
- {
- fNotifiers->DeleteElementsAt(iter.fCurrentIndex, 1);
- fDependents->RemoveDependency(notifier, anObject, kNoLabel);
- }
- }
- }
-
- //========================================================================================
- // CLASS TStandardDependencySpace
- //========================================================================================
- #undef Inherited
- #define Inherited TSimpleDependencySpace
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TStandardDependencySpace,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace constructor
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TStandardDependencySpace::TStandardDependencySpace() :
- fNestedUpdates(NULL),
- fUpdating(FALSE)
- {
- }
- // TStandardDependencySpace::TStandardDependencySpace
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TStandardDependencySpace::~TStandardDependencySpace()
- {
- fNestedUpdates = (TNotificationQueue *)FreeIfObject(fNestedUpdates);
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::NotifierChanged:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TStandardDependencySpace::NotifierChanged(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy)// Override
- {
- if (fUpdating)
- {
- if (!fNestedUpdates)
- fNestedUpdates = TNotificationQueue::NewNotificationQueue();
-
- fNestedUpdates->Queue(Notification(notifier, theChange, changedBy));
- }
- else
- {
- NotifyDependents(notifier, theChange, changedBy);
-
- if (fNestedUpdates)
- {
- while (fNestedUpdates->GetSize() > 0)
- {
- Notification n;
- if (fNestedUpdates->Dequeue(n))
- NotifyDependents(n.fNotifier, n.fChange, n.fChangedBy);
- }
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::NotifyDependents:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TStandardDependencySpace::NotifyDependents(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy)
- {
- if (notifier && (theChange != kNoChange))
- {
- fUpdating = TRUE;
- MarkAllDependents(notifier, TRUE);
- UpdateMarkedObjects(theChange, notifier, changedBy);
- fUpdating = FALSE;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::MarkObject:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
- void TStandardDependencySpace::MarkObject(TObject* anObject,
- Boolean state)
- {
- ArrayIndex index;
- DependencyPtr p;
-
- if (anObject)
- {
- if ((fNotifiers) && fNotifiers->FindPrimaryObject(anObject, index))
- {
- p = (DependencyPtr)fNotifiers->ComputeAddress(index);
- if ((state) != (p->fLabel < 0))
- p->fLabel = -(p->fLabel);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::IsObjectMarked:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
- Boolean TStandardDependencySpace::IsObjectMarked(TObject* anObject)
- {
- Boolean returnVal = FALSE;
-
- ArrayIndex index;
-
- if (anObject && fNotifiers && fNotifiers->FindPrimaryObject(anObject, index))
- returnVal = (((DependencyPtr)fNotifiers->ComputeAddress(index))->fLabel < 0);
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::MarkAllDependents:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
- void TStandardDependencySpace::MarkAllDependents(TObject* notifier,
- Boolean state)
- {
- if (notifier)
- {
- CDependentIterator iter(notifier, this);
-
- for (TObject * dependent = iter.FirstDependent(); iter.More(); dependent = iter.NextDependent())
- {
- if (state != IsObjectMarked(dependent))
- {
- MarkObject(dependent, state);
- MarkAllDependents(dependent, state);
- }
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::UpdateMarkedObjects:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TStandardDependencySpace::UpdateMarkedObjects(ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy)
- {
- DependencyPtr p;
- {
- CArrayIterator iter(fNotifiers);
-
- for (ArrayIndex index = iter.FirstIndex(); iter.More(); index = iter.NextIndex())
- {
- p = (DependencyPtr)fNotifiers->ComputeAddress(index);
- if (p->fLabel < 0)
- HandleUpdate(p->fPrimaryObject, theChange, changedObject, changedBy);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::HandleUpdate:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void TStandardDependencySpace::HandleUpdate(TObject* anObject,
- ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy)
- {
- if (IsObjectMarked(anObject))
- {
- MarkObject(anObject, FALSE);
-
- // ••• This should be changed to iterate rather than recurse
- UpdateNotifiers(anObject, theChange, changedObject, changedBy);
-
- anObject->DoUpdate(theChange, changedObject, changedBy, this);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace::UpdateNotifiers:
- //----------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- void TStandardDependencySpace::UpdateNotifiers(TObject* anObject,
- ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy)
- {
- CNotifierIterator iter(anObject, this);
-
- for (TObject * notifier = iter.FirstNotifier(); iter.More(); notifier = iter.NextNotifier())
- HandleUpdate(notifier, theChange, changedObject, changedBy);
- }
-
-
- //----------------------------------------------------------------------------------------
- // CompareDependency:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CompareResult CompareDependency(ArrayIndex index,
- void* yourDataPtr)
- {
- CDependencyComparer * dependencyInfo = (CDependencyComparer *)yourDataPtr;
-
- return dependencyInfo->fDependencies->CompareElements(&dependencyInfo->fTargetDependency, dependencyInfo->fDependencies->ComputeAddress(index));
- }
-
-
- //========================================================================================
- // CLASS CDependencyIterator
- //========================================================================================
- #undef Inherited
- #define Inherited CArrayIterator
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::CDependencyIterator: CDependentIterator
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CDependencyIterator::CDependencyIterator(TDependencies* theArray,
- TObject* theObject) :
- CArrayIterator(theArray, kIterateForward)
- {
- fObject = theObject;
- }
- // CDependencyIterator::CDependencyIterator
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::~CDependencyIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CDependencyIterator::~CDependencyIterator()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::Reset:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- void CDependencyIterator::Reset() // Override
- {
- if (fDynamicArray)
- {
- ArrayIndex foundIndex;
-
- // Although the lists are ordered the search is a binary search and can return
- // a random entry from the set of matching entries. First back up the the _real_
- // first matching entry and then we will march forward applying the DoToDependency
-
- if (((TDependencies *)(fDynamicArray))->FindPrimaryObject(fObject, foundIndex))
- {
- { // extra block to ensure iterators are destroyed in fifo order
- CArrayIterator iter(fDynamicArray, 1, foundIndex, kIterateBackward);
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- if (((TDependencies *)(fDynamicArray))->PrimaryObjectAt(i) == fObject)
- foundIndex = i;
- else
- break;
- }
- fLowBound = foundIndex;
- }
- }
- else
- fLowBound = kEmptyIndex;
- }
-
- CArrayIterator::Reset();
- }
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::More:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- Boolean CDependencyIterator::More() // Override
- {
- // return CArrayIterator::More() && (CurrentObject() == fObject);
-
- return CArrayIterator::More() && (((TDependencies *)fDynamicArray)->PrimaryObjectAt(CurrentIndex()) == fObject);
- }
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::CurrentObject:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TObject* CDependencyIterator::CurrentObject()
- {
- return ((TDependencies *)fDynamicArray)->SecondaryObjectAt(CurrentIndex());
- }
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::FirstObject:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TObject* CDependencyIterator::FirstObject()
- {
- Reset();
-
- return More() ? ((TDependencies *)fDynamicArray)->SecondaryObjectAt(FirstIndex()) : NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // CDependencyIterator::NextObject:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- TObject* CDependencyIterator::NextObject()
- {
- return ((TDependencies *)fDynamicArray)->SecondaryObjectAt(NextIndex());
- }
-
-
- //========================================================================================
- // CLASS CDependentIterator
- //========================================================================================
- #undef Inherited
- #define Inherited CDependencyIterator
-
- //----------------------------------------------------------------------------------------
- // CDependentIterator::CDependentIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CDependentIterator::CDependentIterator(TObject* theObject,
- TSimpleDependencySpace* dependencySpace) :
- CDependencyIterator(dependencySpace ? dependencySpace->fDependents : NULL, theObject)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CDependentIterator::~CDependentIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CDependentIterator::~CDependentIterator()
- {
- }
-
-
- //========================================================================================
- // CLASS CNotifierIterator
- //========================================================================================
- #undef Inherited
- #define Inherited CDependencyIterator
-
- //----------------------------------------------------------------------------------------
- // CNotifierIterator::CNotifierIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CNotifierIterator::CNotifierIterator(TObject* theObject,
- TSimpleDependencySpace* dependencySpace) :
- CDependencyIterator(dependencySpace ? dependencySpace->fNotifiers : NULL, theObject)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CNotifierIterator::~CNotifierIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment DepRes
-
- CNotifierIterator::~CNotifierIterator()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // End of UDependencies.cp
-
- #pragma segment Inline
-
-